﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using Solidi;

namespace Solidi
{
	/// <summary>
	/// Thread-safe
	/// </summary>
	public sealed class DependencyResolver : IDependencyResolver
	{
		public bool TryResolve(IDependencyContainer container, IDependencyKey key, out object instance)
		{
            if (container == null)
            {
                throw new ArgumentNullException("container");
            }

			object graphId = new object();

			IDependencyResolver resolver = container.Resolver;
			IDependencyComposer composer = container.Composer;
			IDependencyLifetime lifetime = container.Lifetime;

			resolver = new GraphDependencyResolver(graphId, resolver);
			composer = new ContextualDependencyComposer(graphId, composer);
			lifetime = new ContextualDependencyLifetime(graphId, lifetime);

			container = new DependencyContainer(container.Registry, resolver, composer, lifetime);

			return resolver.TryResolve(graphId, container, key, out instance);
		}

		public bool TryResolve(object graphId, IDependencyContainer container, IDependencyKey key, out object instance)
		{
			if (container == null)
			{
				throw new ArgumentNullException("container");
			}

			IDependency dependency = container.Registry.Find(key, null).LastOrDefault();

			if (dependency != null)
			{
				return container.Lifetime.TryAcquire(graphId, container, dependency, out instance);
			}
			else
			{
				instance = null;

				return false;
			}
		}

		public bool TryRelease(IDependencyContainer container, object instance)
		{
			if (container == null)
			{
				throw new ArgumentNullException("container");
			}

			if (instance == null)
			{
				throw new ArgumentNullException("instance");
			}

			return container.Lifetime.TryDiscard(container, instance);
		}
	}
}
